package com.rm.zeyou.exception;

import cn.dev33.satoken.exception.DisableServiceException;
import cn.dev33.satoken.exception.NotLoginException;
import com.rm.zeyou.response.ApiRestResponse;
import org.hibernate.validator.internal.engine.path.PathImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.TypeMismatchException;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.BindingResult;
import org.springframework.web.HttpMediaTypeNotAcceptableException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.io.IOException;
import java.util.Objects;


/**
 * @author ZhangKeChen
 * @date 2022/8/11
 */
@RestControllerAdvice
public class GlobalExceptionHandler {

    private final Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class);

    /**
     * 系统异常
     *
     * @param e
     * @return
     */
    @ExceptionHandler(value = Exception.class)
    public Object handleException(Exception e) {
        log.error("Default Exception: ", e);
        return ApiRestResponse.error(ErrorCodeExceptionEnum.SYSTEM_ERROR);
    }

    /**
     * 自定义异常
     *
     * @param e
     * @return
     */
    @ExceptionHandler(value = ErrorCodeException.class)
    public Object handleInsuranceException(ErrorCodeException e) {
        log.error("errorCodeException: ", e);
        return ApiRestResponse.error(e.getCode(), e.getMsg());
    }

    /**
     * validation 异常捕获
     *
     * @param e
     * @return
     */
    @ExceptionHandler(value = MethodArgumentNotValidException.class)
    public Object handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
        BindingResult bindingResult = e.getBindingResult();
        Objects.requireNonNull(bindingResult.getFieldError());
        return ApiRestResponse.error(ErrorCodeExceptionEnum.PARAM_ERROR.getCode(),
                bindingResult.getFieldError().getField() + " " + bindingResult.getFieldError().getDefaultMessage());
    }

    /**
     * validation 异常捕获
     *
     * @param e
     * @return
     */
    @ExceptionHandler(value = ConstraintViolationException.class)
    public Object handleConstraintViolationException(ConstraintViolationException e) {
        ConstraintViolation<?> violation = e.getConstraintViolations().iterator().next();
        String path = ((PathImpl) violation.getPropertyPath()).getLeafNode().getName();
        String resultMessage = String.format("参数%s%s", path, violation.getMessage());
        return ApiRestResponse.error(ErrorCodeExceptionEnum.PARAM_ERROR.getCode(),
                resultMessage);
    }

    /**
     * validation 异常捕获
     *
     * @param e
     * @return
     */
    @ExceptionHandler(value = MissingServletRequestParameterException.class)
    public Object handleMissingParamExceptionHandle(MissingServletRequestParameterException e) {
        String name = e.getParameterName();
        String type = e.getParameterType();
        String value = e.getMessage();
        // log.info(value);
        String message = String.format("参数%s为空", name);
        return ApiRestResponse.error(ErrorCodeExceptionEnum.PARAM_ERROR.getCode(), message);
    }

    //IOException
    @ExceptionHandler(value = {IOException.class})
    public Object requestIOException(IOException e) {
        log.error("IOException: ", e);
        return ApiRestResponse.error("500", "连接超时,请稍后再试");
    }

    
    //400错误
    @ExceptionHandler(value = {HttpMessageNotReadableException.class, TypeMismatchException.class})
    public Object requestNotReadable(HttpMessageNotReadableException e) {
        log.error("HttpMessageNotReadableException: ", e);
        return ApiRestResponse.error("400", e.getMessage());
    }

    //405错误
    @ExceptionHandler(value = {HttpRequestMethodNotSupportedException.class})
    public Object request405(HttpRequestMethodNotSupportedException e) {
        log.error("HttpRequestMethodNotSupportedException: ", e);
        return ApiRestResponse.error("405", e.getMessage());
    }

    //406错误
    @ExceptionHandler({HttpMediaTypeNotAcceptableException.class})
    public Object request406(HttpMediaTypeNotAcceptableException e) {
        log.error("HttpMediaTypeNotAcceptableException: ", e);
        return ApiRestResponse.error("406", e.getMessage());
    }


    /**
     * 处理未登录的异常
     */
    @ExceptionHandler(value = NotLoginException.class)
    public Object handleNotLoginException(NotLoginException e) {
        log.error("NotLoginException: ", e);
        return ApiRestResponse.error(ErrorCodeExceptionEnum.USER_LOGIN_ERROR.getCode(), ErrorCodeExceptionEnum.USER_LOGIN_ERROR.getMsg());
    }

    /**
     * 处理账号封禁异常
     *
     * @param e
     * @return
     */
    @ExceptionHandler(value = DisableServiceException.class)
    public Object handleDisableServiceException(DisableServiceException e) {
        log.error("DisableServiceException: ", e);
        return ApiRestResponse.error(ErrorCodeExceptionEnum.USER_LOGIN_ERROR.getCode(), e.getMessage());
    }

}
